<template>
  <div>
    <div style="height: 20px;">
      <el-button style="float: right; margin-left: 10px;" type="text" :disabled="(currentStep != 0) || (!gameOverMark)" @click="choosePlayerCountDialogVisible = true">开始游戏</el-button>
      <el-button style="float: right; margin-left: 10px;" type="text" :disabled="(currentStep != 1) || gameOverMark" @click="startPick()">挑选玻璃</el-button>
      <el-button style="float: right; margin-left: 10px;" type="text" :disabled="(currentStep != 1) || (playerPosition[currentPlayer] == 0) || gameOverMark" @click="passPick()">重置位置</el-button>
      <el-button style="float: right; margin-left: 10px;" type="text" :disabled="(pickingPanes.length === 0) || gameOverMark" @click="breakPane()">打碎玻璃</el-button>
      <el-button style="float: right; margin-left: 10px;" type="text" :disabled="false && (currentStep != 3) || (pickingPanes.length > 0) || gameOverMark" @click="turnOver()">回合结束</el-button>
    </div>

    <el-dialog
      title="请选择游戏人数"
      width="20%"
      :visible.sync="choosePlayerCountDialogVisible">
      <el-radio-group v-model="playerCount">
        <el-radio :label="2">2人</el-radio>
        <el-radio :label="3">3人</el-radio>
        <el-radio :label="4">4人</el-radio>
      </el-radio-group>
      <span slot="footer" class="dialog-footer">
        <el-button @click="choosePlayerCountDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="choosePlayerCountDialogVisible = false; start()">确 定</el-button>
      </span>
    </el-dialog>

    <el-row :gutter="3">
      <!-- 宫殿列表 -->
      <el-col :span="14">
        <el-alert
          title="宫殿列表"
          type="success"
          effect="dark"
          :closable="false">
        </el-alert>
        <div
          style="float: left; width: 40%; padding: 10px; margin: 5px; border: 1px solid transparent;"
          :class="palace_index == currentPlayer ? 'currentPalace' : ''"
          v-for="(palace, palace_index) in palaces"
          :key="palace_index">
          <el-divider>玩家{{palace_index + 1}}{{ (firstPickMark == palace_index) ? '（先手）' : ''}}</el-divider>
          <p v-for="(strip, strip_index) in palace" :key="palace_index + '-' + strip_index">
            <!-- {{ strip_index + 1 }}： -->
            <span style="margin-left: 10px; border: 1px solid transparent;" :class="(palaceStatus[palace_index][strip_index] > 0)?'done':''">正</span>：
            <el-button
              type="text"
              :disabled="(palaceStatus[currentPlayer][strip_index] != 0)
                || (currentStep != 3 ) 
                || (palace_index != currentPlayer) 
                || (strip_index < [playerPosition[currentPlayer]])
                || (pickingPanes.length == 0)
                || pane.done
                || ((pickingStripIndex !== -1) && (pickingStripIndex !== strip_index))
                || oneSideFinishLock"
              v-for="(pane, pane_index) in strip[0]"
              :key="palace_index + '-' + strip_index + '-0-' + pane_index"
              @click="mountPane(strip_index, pane_index)"
              :class="pane.done ? 'done': ''">
              {{pane.color}}
            </el-button>
            <span style="margin-left: 10px; border: 1px solid transparent;" :class="(palaceStatus[palace_index][strip_index] > 1)?'done':''">反</span>：
            <el-button
              type="text"
              :disabled="(palaceStatus[currentPlayer][strip_index] != 1)
                || (currentStep != 3 )
                || (palace_index != currentPlayer) 
                || (strip_index < [playerPosition[currentPlayer]])
                || (pickingPanes.length == 0)
                || pane.done
                || ((pickingStripIndex !== -1) && (pickingStripIndex !== strip_index))
                || oneSideFinishLock"
              v-for="(pane, pane_index) in strip[1]"
              :key="palace_index + '-' + strip_index + '-1-' + pane_index"
              @click="mountPane(strip_index, pane_index)"
              :class="pane.done ? 'done': ''">
              {{pane.color}}
            </el-button>
            <span v-if="playerPosition[palace_index] === strip_index">*</span>
          </p>
        </div>
      </el-col>
      <!-- 工场列表 -->
      <el-col :span="5">
        <el-alert
          title="工场列表"
          type="warning"
          effect="dark"
          :closable="false">
        </el-alert>
        <!-- 待安装玻璃 -->
        <div style="height: 50px;">
          <el-divider>待装（{{ pickingPanes.length }}）</el-divider>
          <span v-if="pickingPanes.length > 0">[</span>
          <el-button
            type="text"
            disabled
            v-for="(p, idx) in pickingPanes"
            :key="'pp-'+idx">
            {{ p }} 
          </el-button>
          <span v-if="pickingPanes.length > 0">]</span>
        </div>
        <!-- 大桌 -->
        <div style="height: 130px;">
          <el-divider>大桌（{{ bigTable[0].length + bigTable[1].length + bigTable[2].length + bigTable[3].length + bigTable[4].length }}）</el-divider>
          {{firstPickMark < 0 ? '先手标记待领取（碎玻璃+1）' : ''}}
          <div v-if="b.length > 0" v-for="(b, idx_b) in bigTable" :key="'bt-'+idx_b">
            <span v-if="b.length > 0">[</span>
            <el-button
              type="text"
              :disabled="currentStep != 2"
              @click="pickPaneInBig(idx_b)"
              v-for="(p, idx) in b"
              :key="'btp-'+idx">
              {{ p }} 
            </el-button>
            <span v-if="b.length > 0">]</span>
          </div>
        </div>
        <!-- 小桌 -->
        <div style="height: 100px;">
          <el-divider>小桌</el-divider>
          <div v-if="s.length > 0" v-for="(s, idx_s) in smallTable" :key="'st-'+idx_s" style="float: left;">
            [
            <el-button
              type="text"
              :disabled="currentStep != 2"
              v-for="(p, idx_p) in s"
              @click="pickPaneInSmall(idx_s, p)"
              :key="'stp-' + idx_p">
              {{ p }} 
            </el-button>
            ]
          </div>
        </div>
        <!-- 回收站 -->
        <div style="height: 50px;">
          <el-divider>回收站（{{ recycleBin.length }}）</el-divider>
          <span v-if="recycleBin.length > 0">[</span>
          <el-button
            type="text"
            disabled
            v-for="(p, idx) in recycleBin"
            :key="'r-'+idx">
            {{ p }}
          </el-button>
          <span v-if="recycleBin.length > 0">]</span>
        </div>
        <!-- 玻璃工场 -->
        <div style="height: 100px;">
          <el-divider>工场（{{ panePool.length }}）</el-divider>
          <span v-if="panePool.length > 0">[</span>
          <el-button
            type="text"
            disabled
            v-for="(p, idx) in panePool"
            :key="'pool-'+idx">
            {{ p }}
          </el-button>
          <span v-if="panePool.length > 0">]</span>
        </div>
      </el-col>
      <!-- 信息列表 -->
      <el-col :span="5">
        <el-alert
          title="计分板"
          type="error"
          effect="dark"
          :closable="false">
        </el-alert>
        <!-- 记分牌 -->
        <div style="height: 200px; margin-top: 10px;">
          <el-divider>玩家分数</el-divider>
          <p v-for="(s, i) in scores" :key="'s-'+i">
            玩家{{i+1}}：得{{scores[i]}}，扣{{deductLevel[deductPosition[i]]}}，总{{scores[i]-deductLevel[deductPosition[i]]}}
          </p>
        </div>
        <!-- 信息列表 -->
        <el-alert
          title="信息列表"
          type="info"
          effect="dark"
          :closable="false">
        </el-alert>
        <el-divider>幸运色/轮次</el-divider>
        <p>当前第{{currentRound + 1}}轮</p>
        [
          <span
            :class="idx == currentRound ? 'done': ''"
            v-for="(c, idx) in luckyColor"
            :key="'c-'+idx">
            {{ c }} 
          </span>
        ]
        <el-divider>减扣梯度</el-divider>
        {{ deductLevel }}
        <el-divider>加分规则</el-divider>
        {{ bonusLevel }}
        <p style="color: red">当前步骤：{{ currentStepInfo }}</p>
      </el-col>
    </el-row>

  </div>
</template>

<script>
import { createPalaces, PATTERN_STRIP_COUNT, MAX_ROUND, MAX_DECUCT_LEVEL } from '../utils/palaces.js'
import { createSmallTable, initPaneFactory, paneRecycle, getPanePool } from '../utils/panes.js'
export default {
  data () {
    return {
      playerCount: 2,
      currentPlayer: undefined,
      playerPosition: [],
      palaceStatus: undefined,
      palaces: undefined,
      smallTable: [],
      bigTable: [[],[],[],[],[]],
      panePool: [],
      pickingStripIndex: -1, // 初始为-1，避免干扰
      pickingPanes: [],
      currentStep: 0,
      choosePlayerCountDialogVisible: false,
      oneSideFinishLock: false,
      recycleBin: [], // 回收站
      scores: [],
      currentRound: 0, // 当前轮次，最多MAX_ROUND轮（6轮）
      luckyColor: [0, 1, 2, 3, 4, 0], // 当前轮次的幸运色，可加分
      deductPosition: [],
      deductLevel: [0, 1, 2, 4, 5, 8, 10, 12, 15, 18],
      bonusLevel: [4, 3, 3, 2, 2, 1, 1, 2],
      comboLevel: [0, 0, 3, 6, 10],
      gameOverMark: true, // 游戏结束时标记为true
      firstPickMark: -1 // -1：未领取；0-3：下回合先手玩家id
    }
  },
  computed: {
    currentStepInfo () {
      switch (this.currentStep) {
        case 0:
          return '请选择人数，点击开始游戏'
        case 1:
          return '请选择“挑选玻璃”，或者“放弃挑选，重置小人”'
        case 2:
          return '请挑选玻璃'
        case 3:
          return '请选择你的宫殿里的一面墙去安装玻璃'
        default:
          return ''
      }
    }
  },
  methods: {
    start () {
      this.palaces = createPalaces(this.playerCount)
      initPaneFactory()
      this.smallTable = createSmallTable(this.playerCount)
      this.bigTable = [[],[],[],[],[]] // 第i种颜色，放在第i个数组中
      this.pickingPanes = []
      this.panePool = getPanePool()
      this.currentPlayer = 0
      this.currentStep = 1 // 0：启动游戏; 1：重置/挑选；2：挑选玻璃；2：安装玻璃；
      this.playerPosition = []
      this.palaceStatus = []
      this.scores = []
      this.deductPosition = []
      for (let i = 0; i < this.playerCount; i++) {
        this.playerPosition.push(0)
        this.palaceStatus.push(
          [0, 0, 0, 0, 0, 0, 0, 0] // 0：当前在正面；1：当前在反面；2：当前全部完成
        )
        this.scores.push(0) // 初始分数为0
        this.deductPosition.push(0) // 初始扣分位置为0
      }
      this.currentRound = 0
      this.gameOverMark = false
    },
    turnOver () {
      // 计算大桌是否有剩余
      let bigTableOver = true
      for (let i = 0; i < this.bigTable.length; i++) {
        bigTableOver &= (this.bigTable[i].length == 0)
      }
      // 计算小桌是否有剩余
      let smallTableOver = true
      for (let i = 0; i < this.smallTable.length; i++) {
        smallTableOver &= (this.smallTable[i].length == 0)
      }
      // 大小桌都清空，回合结束
      if (bigTableOver && smallTableOver) {
        if (this.currentRound == (MAX_ROUND - 1)) {
          // 游戏结束
          this.gameOver()
        } else {
          this.nextRound()
        }
      } else {
        // 回合未结束，下一玩家操作
        this.nextPlayer(false)
      }
    },
    gameOver () {
      // 遍历玩家
      for (let i = 0; i < this.playerCount; i++) {
        let combo = 0
        // 遍历窗格，每2个计算一次
        for (let j = 0; j < PATTERN_STRIP_COUNT; j=j+2) {
          // 计算两面的完成度
          let combo = this.palaceStatus[i][j] + this.palaceStatus[i][j+1]
          this.scores[i] += this.comboLevel[combo]
        }
        // 清算待扣分数
        this.scores[i] -= this.deductLevel[this.deductPosition[i]]
        this.deductPosition[i] = 0
      }
      this.resetGame()
    },
    resetGame () {
      // TODO 和start game可适当合并
      this.currentStep = 0
      this.currentPlayer = 0
      this.currentRound = 0
      this.gameOverMark = true
    },
    nextRound () {
      this.currentRound += 1
      // 回收碎玻璃
      let len = this.recycleBin.length
      for (let i = 0; i < len; i++) {
        let p = this.recycleBin.shift()
        paneRecycle(p)
      }
      // 重新填充小桌
      this.smallTable = createSmallTable(this.playerCount)
      this.nextPlayer(true) // 新回合要传参true
    },
    pickPaneInSmall (index, color) {
      for (let i = 0; i < 4; i++) {
        let p = this.smallTable[index].shift()
        if (p === color) {
          this.pickingPanes.push(p)
        } else {
          this.bigTable[p].push(p)
        }
      }
      this.currentStep = 3 // 开始安装玻璃
    },
    pickPaneInBig (color) {
      if (this.firstPickMark < 0) {
        this.firstPickMark = this.currentPlayer
        this.deduct() // 首个拿大桌的玩家碎一块玻璃
      }
      let len = this.bigTable[color].length
      for (let i = 0; i < len; i++) {
        this.pickingPanes.push(this.bigTable[color].shift())
      }
      this.pickingStripIndex = -1
      this.currentStep = 3 // 开始安装玻璃
    },
    breakPane () {
      let p =this.pickingPanes.shift()
      this.deduct()
      this.recyclePane(p)
    },
    mountPane (strip_index, pane_index) {
      // 没有待装玻璃就直接返回
      if (this.pickingPanes.length == 0) return
      // 调整选中玻璃状态
      let side = this.palaceStatus[this.currentPlayer][strip_index]
      let pane = this.palaces[this.currentPlayer][strip_index][side][pane_index]
      let pickedColor = this.pickingPanes[0]
      // 兼容赖子，赖子的颜色是5
      if (pane.color !== 5 && pickedColor !== pane.color) return // 非赖子且颜色不一致直接返回
      this.setCurrentPosition(strip_index)
      this.pickingStripIndex = strip_index
      pane.done = true
      // 判定strip单侧是否结束
      let stripDone = true
      for (let i = 0; i < 5; i++) {
        stripDone = stripDone && this.palaces[this.currentPlayer][strip_index][side][i].done
      }
      if (stripDone) {
        // 如果strip单侧结束
        // 回收单侧玻璃
        for (let i = 0; i < 5; i++) {
          let p = this.palaces[this.currentPlayer][strip_index][side][i].color
          // 和幸运色同色可加分
          if (p == this.luckyColor[this.currentRound]) {
            this.scores[this.currentPlayer] += 1
          }
          this.recyclePane(p)
        }
        // 则strip状态+1，表示进入反面
        this.palaceStatus[this.currentPlayer][strip_index] += 1
        this.oneSideFinishLock = true // 单侧完成时，不允许直接开始安装反面
        // 正面完成时可结算分数
        if (this.palaceStatus[this.currentPlayer][strip_index] == 1) {
          this.settle(strip_index)
        }
      }
      this.$forceUpdate() // 解决多维数组无法触发双向绑定渲染的问题
      // 减扣picking库存
      this.pickingPanes.shift()
    },
    nextPlayer (isNewRound) {
      if (isNewRound) {
        // 新回合开始，轮到优先选择权的玩家
        this.currentPlayer = this.firstPickMark
        this.firstPickMark = -1
      } else {
        // 不是新回合，直接下一个玩家
        if (this.currentPlayer >= (this.playerCount - 1)) {
          this.currentPlayer = 0
        } else {
          this.currentPlayer = this.currentPlayer + 1
        }
      }
      this.currentStep = 1 // 开始选择重置/挑选
      this.pickingStripIndex = -1
      this.oneSideFinishLock = false
    },
    deduct () {
      let s = this.deductPosition[this.currentPlayer] // 获取当前梯度
      if (s == (MAX_DECUCT_LEVEL - 1)) {
        // 达到梯度最大值，扣分后梯度归零
        this.scores[this.currentPlayer] -= this.deductLevel[MAX_DECUCT_LEVEL - 1]
        this.deductPosition[this.currentPlayer] = 0
      } else {
        // 未达到梯度最大值，梯度加1
        this.deductPosition[this.currentPlayer] += 1
      }
    },
    settle (lastFinishStrip) {
      // 从后往前算分
      for (let i = PATTERN_STRIP_COUNT - 1; i >= lastFinishStrip; i--) {
        if (this.palaceStatus[this.currentPlayer][i] > 0) {
          // 正面完成就算分
          this.scores[this.currentPlayer] += this.bonusLevel[i]
        }
      }
    },
    recyclePane (p) {
      this.recycleBin.push(p)
    },
    startPick() {
      this.currentStep = 2 // 开始挑选玻璃
    },
    passPick() {
      this.setCurrentPosition(0)
      this.nextPlayer(false)
    },
    getCurrentPosition () {
      return this.playerPosition[this.currentPlayer]
    },
    setCurrentPosition (p) {
      this.playerPosition[this.currentPlayer] = p
    },
    getCurrentPalace () {
      return this.palaces[this.currentPlayer]
    }
  }
}
</script>

<style scoped>
.done {
  border: 1px solid #000000 !important;
}
.currentPalace {
  border: 1px solid #000000 !important;
}
div /deep/ .el-button {
  padding: 0
}
div /deep/ .el-button {
  padding: 0
}
</style>